const express = require("express") // 引入express模块
// 加载环境变量配置
const config = require('./config/dotenv');

const app = express() // 创建express应用
const server = require('http').createServer(app) // 创建http服务器
const createSocketServer = require('./util/socketServer'); // 引入socketServer模块
const io = createSocketServer(server) // 创建socket.io实例
const ioFun = require("./util/ioFun") // 引入ioFun模块
const path = require('path')
const { tokenCheck } = require("./util/tokenCheck")
const { dateFormat } = require("./util/dateFormat")
const { runAllHealthChecks } = require("./util/healthCheck")
const { corsFun } = require("./util/corsFun") // 引入corsFun模块

app.use(express.json({
    limit: '5mb'
}));
app.use(express.urlencoded({
    limit: '5mb',
    extended: true,
    // extended: false,
    parameterLimit: 50000
}))


app.all('*', corsFun)
//#region 
//     (req, res, next) => {
//     // google需要配置，否则报错cors error
//     res.setHeader('Access-Control-Allow-Credentials', 'true')
//     // 允许的地址,http://127.0.0.1:9000这样的格式
//     // 处理Origin可能为undefined的情况
//     const origin = req.get('Origin');
//     if (origin) {
//         res.setHeader('Access-Control-Allow-Origin', origin);
//     }
//     // res.setHeader('Access-Control-Allow-Origin', '*')
//     // 允许跨域请求的方法
//     res.setHeader(
//         'Access-Control-Allow-Methods',
//         'POST, GET, OPTIONS, DELETE, PUT'
//     )
//     //使用axios发送跨域请求时，设置后Authorization才能被axios响应拦截器获取
//     res.setHeader(
//         "Access-Control-Expose-Headers", "Authorization"
//     )
//     // 允许跨域请求header携带哪些东西
//     res.header(
//         'Access-Control-Allow-Headers',
//         'Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since, authorization'
//     )
//     next()
// }
// )
//#endregion 

// 添加静态文件服务，放在身份验证中间件之前
app.use(express.static(path.join(__dirname, 'dist')))

// 处理favicon.ico请求
app.get('/favicon.ico', (req, res) => {
    res.status(204).send();
})

//#region 
app.use((req, res, next) => {
    // 使用 req.socket.remoteAddress 替代 req.connection.remoteAddress
    let clientIp = req.socket.remoteAddress
    let sessionInfo = !req.body.sessionInfo ? req.query.sessionInfo : req.body.sessionInfo
    //登录、预检、退出、ico图标无需token验证
    if (req.method === 'OPTIONS' || req.url === "/xfjc/login"
        || req.url === "/xfjc/login/userInfo" || req.url === "/xfjc/index/userLogout"
        || /^\/favicon\.ico(\?.*)?$/i.test(req.url)) {
        next()
    } else {
        if (!req.headers.authorization || !req.headers.authorization.startsWith('Bearer ')) {
            return res.status(401).json({ status: 0, msg: '未提供有效的Authorization头' });
        }
        let token = req.headers.authorization.split(' ')[1];
        // console.log(token)
        if (token) {
            // token 校验 
            let tc = tokenCheck(token, clientIp, sessionInfo)
            tc.then(tcRes => {
                // console.log(tcRes)
                if (tcRes.status === false) {
                    res.json({
                        status: 0,
                        msg: tcRes.msg
                    })
                } else {
                    res.setHeader('Authorization', tcRes)
                    next()
                }
            }).catch(err => {
                console.log(err);
                next(err)
            })
        } else {
            console.log("err")
            return false
        }
    }
})
//#endregion

//导入路由模块
const loginRouter = require('./router/login')
app.use("/xfjc", loginRouter);

const indexRouter = require('./router/index')
app.use("/xfjc", indexRouter);

const usersRouter = require('./router/admin/users')
app.use("/xfjc", usersRouter)

const dirsRouter = require('./router/admin/dirs')
app.use("/xfjc", dirsRouter)

const authoritysRouter = require('./router/admin/authority')
app.use("/xfjc", authoritysRouter)

const rolesRouter = require('./router/admin/roles')
app.use("/xfjc", rolesRouter)

const worklogRouter = require('./router/worklog/worklog')
app.use("/xfjc", worklogRouter)

const jobRouter = require('./router/worklog/job')
app.use("/xfjc", jobRouter)

const sessionsRouter = require('./router/admin/sessions')
app.use("/xfjc", sessionsRouter)

const jcdaDeviceRouter = require('./router/jcdata/device')
app.use("/xfjc", jcdaDeviceRouter)

const jcDataRouter = require('./router/jcdata/jcData')
app.use("/xfjc", jcDataRouter)

const jcDataWriteRouter = require('./router/jcdata/jcDataWrite')
app.use("/xfjc", jcDataWriteRouter)

const jcProgressRouter = require('./router/jcdata/jcProgress')
app.use("/xfjc", jcProgressRouter)

const gccListRouter = require('./router/jcdata/gccList')
app.use("/xfjc", gccListRouter)

const crtListRouter = require('./router/jcdata/crtList')
app.use("/xfjc", crtListRouter)

const compDateDistributionRouter = require('./router/jcdata/CompDateDistribution')
app.use("/xfjc", compDateDistributionRouter)

const fasRecordCheckRouter = require('./router/jcdata/fasRecordCheck')
app.use("/xfjc", fasRecordCheckRouter)

const mcsListRouter = require('./router/jcdata/mcsList')
app.use("/xfjc", mcsListRouter)

const mcsDeviceMiddleRouter = require('./router/jcdata/McsDeviceMiddle')
app.use("/xfjc", mcsDeviceMiddleRouter)

const mcsRecordCheckRouter = require('./router/jcdata/mcsRecordCheck')
app.use("/xfjc", mcsRecordCheckRouter)

const areaRouter = require('./router/comminfo/area')
app.use("/xfjc", areaRouter)

const subsysRouter = require('./router/comminfo/subsys')
app.use("/xfjc", subsysRouter)

const persongroupRouter = require('./router/comminfo/persongroup')
app.use("/xfjc", persongroupRouter)

const specialtyRouter = require('./router/comminfo/sepecialty')
app.use("/xfjc", specialtyRouter)

const lbValuesRouter = require('./router/lpsData/lb_values')
app.use("/xfjc", lbValuesRouter)

const lbListRouter = require('./router/lpsData/lb_list')
app.use("/xfjc", lbListRouter)

const lbPersonConfigRouter = require('./router/lpsData/lb_personConfig')
app.use("/xfjc", lbPersonConfigRouter)

const lbPlanRouter = require('./router/lpsData/lb_plan')
app.use("/xfjc", lbPlanRouter)

const basDataRouter = require('./router/autoMationDevData/basData')
app.use("/xfjc", basDataRouter)



//配置全局错误处理中间件
app.use((err, req, res, next) => {
    console.log(dateFormat(new Date()) + " 全局错误处理中间件" + err)
    //token失效
    if (err.name === "UnauthorizedError") {
        return res.json({
            status: 401,
            mag: "无效的token"
        })
    }
    res.json({
        status: 500,
        msg: "未知错误," + err
    })
})

/**
 * 配置socket.io
 * @param {*} io socket.io实例
 */
ioFun(io)


// 执行健康检查并启动服务器
async function startServer() {
    try {
        // 执行健康检查
        const healthCheckResult = await runAllHealthChecks(config.PORT);
        
        // 如果健康检查通过，则启动服务器
        if (healthCheckResult.allChecksPassed) {
            // 监听服务器开始事件
            server.listen(config.PORT, () => {
                console.log(dateFormat(new Date()) + ` 服务器已启动在${config.PORT}端口,socket.io已就绪`);
            })
        } else {
            // 如果健康检查失败，则在一段时间后退出进程
            console.error(dateFormat(new Date()) + " 健康检查失败，无法启动服务器，进程将在5秒后退出...");
            setTimeout(() => {
                process.exit(1);
            }, 5000);
        }
    } catch (error) {
        console.error(dateFormat(new Date()) + " 启动服务器时发生错误:", error);
        // 在错误情况下也退出进程
        setTimeout(() => {
            process.exit(1);
        }, 5000);
    }
}

// 启动服务器
startServer();

// 监听服务器关闭事件
server.on('close', () => {
    console.log(dateFormat(new Date()) + " 服务器已关闭");
    // 关闭socket.io连接
    io.close();
});

// 处理进程终止信号
process.on('SIGINT', () => {
    console.log(dateFormat(new Date()) + " 接收到终止信号，正在关闭服务器...");
    server.close(err => {
        if (err) {
            console.error('服务器关闭错误:', err);
            process.exit(1);
        }
        process.exit(0);
    });
})

// 处理进程正常退出
process.on('exit', () => {
    console.log(dateFormat(new Date()) + " 进程已退出");
});